package com.qingcloud.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingcloud.task.dto.TaskListDTO;
import com.qingcloud.task.dto.TaskSaveDTO;
import com.qingcloud.task.enums.TaskEnum;
import com.qingcloud.task.mapper.TaskMapper;
import com.qingcloud.task.model.Task;
import com.qingcloud.task.model.TaskUser;
import com.qingcloud.task.service.*;
import com.qingcloud.task.util.PageUtil;
import com.qingcloud.task.vo.PageVO;
import com.qingcloud.task.vo.TaskInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 勘察任务表 服务实现类
 * </p>
 *
 * @author zhengjibin
 * @since 2022-01-20
 */
@Slf4j
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
    @Resource
    private TaskMapper taskMapper;
    @Autowired
    private TaskUserService taskUserService;
    @Autowired
    private TaskFileService taskFileService;
    @Autowired
    private TaskRelationService taskRelationService;
    @Autowired
    private TaskTransferService taskTransferService;
    @Autowired
    private TaskSourceService taskSourceService;


    /**
     * 新增保存 任务
     */
    @Transactional
    @Override
    public Long saveTask(TaskSaveDTO dto) {
        verifyData(dto);
        Task task = new Task();
        BeanUtils.copyProperties(dto,task);
        task.setTaskCode(getTaskCode(dto.getSource()));
        task.setStartTime(LocalDateTime.parse(dto.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        task.setEndTime(LocalDateTime.parse(dto.getEndTime(),DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        taskMapper.insert(task);
        //保存任务执行人
        taskUserService.saveUser(dto.getUserIds(),task.getTaskId());
        //保存文件
        taskFileService.saveFile(dto.getFileUrl(),dto.getType(),task.getTaskId(),1);
        //保存任务关联设备，点位，企业
        taskRelationService.saveRelation(dto.getRelationIds(),dto.getRelationType(),task.getTaskId());

        //保存来源 关联数据id
        taskSourceService.saveSource(dto.getSourceIds(),dto.getDataType(),task.getTaskId());

        return task.getTaskId();
    }

    /**
     * 任务基本信息查询
     * @param taskId 任务id
     */
    @Override
    public TaskInfoVO getTaskInfo(Long taskId) {
        Task task = taskMapper.selectById(taskId);
        if (task == null){
            throw new RuntimeException("数据不存在");
        }
        TaskInfoVO vo = new TaskInfoVO();
        BeanUtils.copyProperties(task,vo);
        return vo;
    }

    /**
     * 查询列表
     */
    @Override
    public PageVO<TaskInfoVO> selectPage(TaskListDTO dto) {
        if (dto.getSource() == null){
            throw new RuntimeException("来源不能为空");
        }
        dto.startPage();

        Page<Task> page = new PageUtil<Task>(dto).getPage();
        QueryWrapper<Task> wrapper = new QueryWrapper();
        wrapper.eq("source", dto.getSource())
                .eq(dto.getType()!= null,"type",dto.getType())
                .eq(dto.getStatus() != null,"status",dto.getStatus())
                .ge(dto.getStartTime() != null,"start_time",dto.getStartTime())
                .le(dto.getEndTime() != null , "end_time",dto.getEndTime());
        wrapper.like(StringUtils.isNotBlank(dto.getTaskName()),"task_name",dto.getTaskName());
        wrapper.orderByDesc("create_time");
        page = taskMapper.selectPage(page,wrapper);
        PageVO<TaskInfoVO> pageVO = new PageVO();
        if (CollectionUtils.isEmpty(page.getRecords())){
            return pageVO;
        }
        List<Task> records = page.getRecords();
        List<TaskInfoVO> vos = new ArrayList<>();
        records.forEach(e -> {
            TaskInfoVO taskInfoVO = new TaskInfoVO();
            BeanUtils.copyProperties(e,taskInfoVO);
            vos.add(taskInfoVO);
        });
        pageVO = PageVO.getPage(page);
        pageVO.setList(vos);
        return pageVO;
    }

    @Override
    public List<TaskInfoVO> selectListByIds(Collection<? extends Serializable> ids) {
        List<Task> taskList = listByIds(ids);
        if (CollectionUtils.isEmpty(taskList)){
            throw new RuntimeException("任务不存在");
        }
        List<TaskInfoVO> voList = new ArrayList<>();
        taskList.forEach(e -> {
            TaskInfoVO vo = new TaskInfoVO();
            BeanUtils.copyProperties(e,vo);
            voList.add(vo);
        });
        return voList;
    }

    @Override
    public void updateTask(TaskInfoVO vo) {
        if (vo.getTaskId() == null){
            throw new RuntimeException("数据id不能为空");
        }
        Task task = taskMapper.selectById(vo.getTaskId());
        if (task == null){
            throw new RuntimeException("数据不存在");
        }
        //反射赋值
        Class<? extends Task> taskClass = task.getClass();
        Class<? extends TaskInfoVO> aClass = vo.getClass();
        Field[] fields = aClass.getDeclaredFields();
        boolean flag = false;
        for (Field f : fields){
            String name = f.getName();
            if (name.equals("taskId")){
                continue;
            }
            f.setAccessible(true);
            try {
                Object obj = f.get(vo);
                if (obj != null){
                    Field taskField = taskClass.getDeclaredField(name);
                    taskField.setAccessible(true);
                    taskField.set(task, obj);
                    flag = true;
                }
            } catch (IllegalAccessException e) {
                log.error("修改任务对象发射赋值异常:{}",name);
                e.printStackTrace();
            }catch (NoSuchFieldException e2){
                log.error("修改任务对象发射赋值异常:{}",name);
                e2.printStackTrace();
            }
        }
        if (flag){
            taskMapper.updateById(task);
        }
    }

    /**
     * 任务转派
     * @param userId 源 执行人id
     * @param toUserId 被转派人id
     */
    @Transactional
    @Override
    public void taskTransfer(Long taskId,String userId, String toUserId) {
        Task task = taskMapper.selectById(taskId);
        if (task == null){
            throw new RuntimeException("任务不存在");
        }
        if (task.getStatus().intValue() != 0){
            throw new RuntimeException("任务已开始，不能转派");
        }
        taskTransferService.save(taskId,userId,toUserId);
        //修改执行人
        taskUserService.updateUser(taskId,toUserId);
    }

    /**
     * 任务 接收，进入开始状态
     */
    @Override
    public void receive(Long taskId, String userId) {
        Task task = queryTaskUpdate(taskId, userId);
        task.setStatus(TaskEnum.status.ONE.code);
        task.setUpdateUser(userId);
        taskMapper.updateById(task);
    }


    @Override
    public void complete(Long taskId, String userId) {
        Task task = queryTaskUpdate(taskId, userId);
        task.setStatus(TaskEnum.status.TWO.code);
        task.setUpdateUser(userId);
        taskMapper.updateById(task);
    }

    private Task queryTaskUpdate(Long taskId,String userId){
        Task task = taskMapper.selectById(taskId);
        if (task == null){
            throw new RuntimeException("数据不存在");
        }
        if (task.getStatus().intValue() != 0){
            throw new RuntimeException("任务已开始或已完成，请刷新重试");
        }
        //查询执行人
        TaskUser user = taskUserService.selectByTaskId(task.getTaskId());
        if (user == null){
            throw new RuntimeException("数据异常，执行人不存在");
        }
        if (!userId.equals(user.getUserId())){
            throw new RuntimeException("执行认错，任务可能已经被重新指派，请刷新重试");
        }
        return task;
    }

    private String getTaskCode(Integer type){
        if (type.intValue() == 1){
            return "WRY"+System.currentTimeMillis();
        }else if (type.intValue() == 2){
            return "SHJ" + System.currentTimeMillis();
        }
        return System.currentTimeMillis()+"";
    }
    private void verifyData(TaskSaveDTO dto) {
        if (StringUtils.isBlank(dto.getTaskName()) || dto.getSource() == null){
            throw new RuntimeException("数据不能为空");
        }
        LocalDateTime localDateTime = LocalDateTime.now();
        Class<? extends TaskSaveDTO> aClass = dto.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field f : fields){
            String name = f.getName();
            f.setAccessible(true);
            Object obj = null;
            try {
                obj = f.get(dto);
            } catch (IllegalAccessException e) {
                log.error("保存任务对象发射赋值异常:{}",name);
                e.printStackTrace();
            }
            if (obj == null && !name.equals("remarks") && !name.equals("fileUrl")
                    && !name.equals("relationIds") && !name.equals("sourceIds")){
                throw new RuntimeException(name+"不能为空");
            }

        }
        if (localDateTime.compareTo(LocalDateTime.parse(dto.getStartTime(),DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) > 0){
            throw new RuntimeException("开始时间不能小于当前时间");
        }
        if (dto.getStartTime().compareTo(dto.getEndTime()) >= 0){
            throw new RuntimeException("开始时间必须大于结束时间");
        }
    }
}
